package com.pmcc.core.config.security;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * jwt 验证每个controller 都需要调用的类
 */
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private final Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.header}")
    private String tokenHeader;

    /**
     * 每个接口都需要调用的方法
     * @param request
     * @param response
     * @param chain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
     //从header里面取出来token
        String authToken = request.getHeader(this.tokenHeader);
     //根据token获得用户名
        String username = jwtTokenUtil.getUsernameFromToken(authToken);
        //如果得到的用户名不为空，或则获得当前的线程里面的权限不为空
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            //根据用户名加载jwtUser ，此处的UserDetails 是jwtUser的接口类
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            //验签,根据token 和jwtUser验证
            if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                //根据新的jwtUser 生成 authentication
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
               //把新的authentication 加载到线程里面
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        chain.doFilter(request, response);
    }
}